#include "OgreStableHeaders.h"

#include "OgreBone.h"
#include "OgreSkeleton.h"

namespace Ogre
{
	Bone::Bone(unsigned short handle, Skeleton* creator)
		: Node(), mHandle(handle), mManuallyControlled(false), mCreator(creator)
	{
	}

	Bone::Bone(const String& name, unsigned short handle, Skeleton* creator)
		: Node(name), mHandle(handle), mManuallyControlled(false), mCreator(creator)
	{
	}

	Bone::~Bone()
	{
	}

	Bone* Bone::createChild(unsigned short handle, const Vector3& inTranslate,
		const Quaternion& inRotate)
	{
		Bone* retBone = mCreator->createBone(handle);
		retBone->translate(inTranslate);
		retBone->rotate(inRotate);
		this->addChild(retBone);
		return retBone;
	}

	Node* Bone::createChildImpl(void)
	{
		return mCreator->createBone();
	}

	Node* Bone::createChildImpl(const String& name)
	{
		return mCreator->createBone(name);
	}

	void Bone::setBindingPose(void)
	{
		setInitialState();

		mBindDerivedInversePosition = -_getDerivedPosition();
		mBindDerivedInverseScale = Vector3::UNIT_SCALE / _getDerivedScale();
		mBindDerivedInverseOrientation = _getDerivedOrientation().Inverse();
	}

	void Bone::reset(void)
	{
		resetToInitialState();
	}

	void Bone::setManuallyControlled(bool manuallyControlled)
	{
		mManuallyControlled = manuallyControlled;
		mCreator->_notifyManualBondStateChange(this);
	}

	bool Bone::isManuallyControlled() const
	{
		return mManuallyControlled;
	}

	void Bone::_getOffsetTransform(Matrix4& m) const
	{
		Vector3 locScale = _getDerivedScale() * mBindDerivedInverseScale;

		Quaternion locRotate = _getDerivedOrientation() * mBindDerivedInverseOrientation;

		Vector3 locTranslate = _getDerivedPosition() + locRotate * (locScale * mBindDerivedInversePosition);

		m.makeTransform(locTranslate, locScale, locRotate);
	}

	unsigned short Bone::getHandle(void) const
	{
		return mHandle;
	}

	void Bone::needUpdate(bool forceParentUpdate)
	{
		Node::needUpdate(forceParentUpdate);

		if (isManuallyControlled())
		{
			mCreator->_notifyManualBonesDirty();
		}
	}
}
